
/*
 * Copyright (C) 2008-2009 Archie L. Cobbs. All rights reserved.
 *
 * $Id: ListTest1.java 377 2010-03-11 20:50:18Z archie.cobbs $
 */

package org.dellroad.sidekar;

import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;

import org.dellroad.sidekar.annotation.SidekarEntity;
import org.dellroad.sidekar.annotation.SidekarList;
import org.dellroad.sidekar.util.VoidDatabaseAction;
import org.dellroad.stuff.util.LinkedList;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;

public class ListTest1 extends DatabaseTest {

    @Test
    public void testList1() {

        // Populate
        this.db.performTransaction(null, new VoidDatabaseAction() {
            public void executeVoid() {
                testList();
            }
        });
    }

    protected void testList() {

        Top top = this.db.create(Top.class);
        LinkedList<Integer> list = top.getList();

        assertNull(list.peek());
        assertNull(list.poll());

        list.add(123);
        assertEquals((int)list.peek(), 123);
        assertFalse(list.isEmpty());
        assertEquals((int)list.peek(), 123);
        assertEquals((int)list.poll(), 123);
        assertTrue(list.isEmpty());
        assertNull(list.peek());
        assertNull(list.poll());

        list.add(123);
        assertEquals(list.size(), 1);
        assertEquals((int)list.iterator().next(), 123);
        assertEquals((int)list.peek(), 123);
        assertEquals(list, Arrays.asList(new Integer[] { 123 }));

        list.addFirst(456);
        assertEquals(list.size(), 2);
        assertEquals((int)list.getFirst(), 456);
        assertEquals(list, Arrays.asList(new Integer[] { 456, 123 }));

        list.addLast(-456);
        assertEquals(list.size(), 3);
        assertEquals((int)list.getFirst(), 456);
        assertEquals((int)list.getLast(), -456);
        assertEquals(list, Arrays.asList(new Integer[] { 456, 123, -456 }));

        ListIterator<Integer> i = list.listIterator();
        assertTrue(i.hasNext());
        assertFalse(i.hasPrevious());
        assertEquals((int)i.next(), 456);
        assertTrue(i.hasNext());
        assertTrue(i.hasPrevious());
        assertEquals((int)i.next(), 123);
        assertTrue(i.hasNext());
        assertTrue(i.hasPrevious());
        i.remove();
        assertEquals(list.size(), 2);
        assertTrue(i.hasNext());
        assertTrue(i.hasPrevious());
        assertEquals((int)i.previous(), 456);
        assertTrue(i.hasNext());
        assertFalse(i.hasPrevious());
        assertEquals((int)i.next(), 456);
        assertTrue(i.hasNext());
        assertTrue(i.hasPrevious());
        assertEquals((int)i.next(), -456);
        assertFalse(i.hasNext());
        assertTrue(i.hasPrevious());

        // Now detach the item containing the list and all list methods should stop working
        top.sidekarDetach();
        try {
            list.remove();
            assert false;
        } catch (DetachedItemException e) {
            // expected
        }
        try {
            list.add(456);
            assert false;
        } catch (DetachedItemException e) {
            // expected
        }
        try {
            list.listIterator().hasNext();
            assert false;
        } catch (DetachedItemException e) {
            // expected
        }
        try {
            list.iterator().next();
            assert false;
        } catch (DetachedItemException e) {
            // expected
        }

        top.sidekarAttach();
        assertTrue(list.isEmpty());

        list.add(456);
        assertFalse(list.isEmpty());
        assertEquals((int)list.poll(), 456);
        assertTrue(list.isEmpty());
    }

    @Override
    protected List<Class<?>> getSchemaClasses() {
        return Arrays.<Class<?>>asList(Top.class);
    }

    // Model classes

    @SidekarEntity
    public abstract static class Top implements Item {

        @SidekarList
        public abstract LinkedList<Integer> getList();
    }
}

